package cn.factorybox.item.service.impl;

import cn.factorybox.common.entity.Constant;
import cn.factorybox.common.utils.BeanMapUtils;
import cn.factorybox.common.utils.CodecUtils;
import cn.factorybox.common.utils.IpUtils;
import cn.factorybox.common.utils.UUIDUtil;
import cn.factorybox.entity.UserInfo;
import cn.factorybox.item.config.JwtProperties;
import cn.factorybox.item.mapper.CompanyMapper;
import cn.factorybox.item.mapper.SystemLogMapper;
import cn.factorybox.item.mapper.UserMapper;
import cn.factorybox.item.service.UserService;
import cn.factorybox.model.entity.Company;
import cn.factorybox.model.entity.SystemLog;
import cn.factorybox.model.entity.User;
import cn.factorybox.model.entity.UserUpdate;
import cn.factorybox.utils.JwtUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author flypig
 * @version 1.0
 * @date 2020-03-28 11:11
 */
@Service
public class UserServiceImpl implements UserService {

    private Integer page;

    private Integer size;

    private final static Logger log = LoggerFactory.getLogger(UserServiceImpl.class);

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private SystemLogMapper systemLogMapper;

    @Autowired
    private JwtProperties jwtProperties;

    @Autowired
    private CompanyMapper companyMapper;

    @Override
    public int register(User user) {

        user.setId(UUIDUtil.uuid());

        String salt = CodecUtils.generateSalt();
        user.setSalt(salt);

        if (StringUtils.isBlank(user.getuPass())) {
            user.setuPass(Constant.USER_INITIAL_PASSWORD);
        }

        // 加盐加密
        user.setuPass(CodecUtils.md5Hex(user.getuPass(), salt));

        user.setuCreateTime(new Date());
        user.setRoles("manager");
        user.setuHeadpath("01");
        user.setuRemark("管理员");
        return this.userMapper.insertUser(user);
    }

    @Override
    public int deleteUser(String id) {
        return userMapper.deleteUser(id);
    }

    @Override
    public String updateUser(User user) throws Exception {
        // 查找到的用户信息
        User userInfo = userMapper.selectUserById(user.getId());
        if (StringUtils.isNotBlank(user.getOldPassword()) && StringUtils.isNotBlank(user.getNewPassword())) {
            // 先查找出该用户的信息，将用户输入密码与查找出的盐进行加密后与数据库中的加密后密码进行比对
            String encryptPassword = CodecUtils.md5Hex(user.getOldPassword(), userInfo.getSalt());
            if (encryptPassword.equals(userInfo.getuPass())) {
                // 输入旧密码正确，重新加盐加密
                String salt = CodecUtils.generateSalt();
                user.setSalt(salt);
                user.setuPass(CodecUtils.md5Hex(user.getNewPassword(), salt));
            } else {
                // 密码验证失败
                return null;
            }
        }
        userMapper.updateUser(user);
        // 更新成功，重新生成token
        User newUser = userMapper.selectUserById(user.getId());
        UserInfo uInfo = new UserInfo();
        uInfo.setId(newUser.getId());
        uInfo.setUsername(newUser.getuName());
        uInfo.setPhone(newUser.getuPhone());
        uInfo.setEmail(newUser.getuEmail());
        List<String> roles = new ArrayList<>();
        roles.add(newUser.getRoles());
        uInfo.setRoles(roles);
        uInfo.setCompanyId(newUser.getCompanyId());
        return JwtUtils.generateToken(uInfo, this.jwtProperties.getKey(), this.jwtProperties.getExpire());
    }

    @Override
    public User selectUser(String uName, String uPass, String ip) {
        User record = new User();
        record.setuName(uName);
        User user = this.userMapper.selectUser(record);

        if (!checkObjFieldIsNotNull(user)) {
            // System.out.println("查无此用户");
            log.warn("查无此用户");
            return null;
        }
        // 获取盐，对用户输入的密码加盐加密
        uPass = CodecUtils.md5Hex(uPass, user.getSalt());

        // 和数据库中的密码进行比较
        if (StringUtils.equals(uPass, user.getuPass())) {
//            System.out.println(user);
            // 登录成功，写入日志
            addLoginLog(ip, user);
            return user;
        }
        log.error("密码有误");
        return null;
    }

    @Override
    public User selectUserWithoutIp(Map<String,Object> map) {
        User record = new User();
        record.setuName((String) map.get("username"));
        User user = this.userMapper.selectUser(record);
        if (!checkObjFieldIsNotNull(user)) {
            // System.out.println("查无此用户");
            log.warn("查无此用户");
            return null;
        }
        // 获取盐，对用户输入的密码加盐加密
        String password = CodecUtils.md5Hex((String) map.get("password"), user.getSalt());

        // 和数据库中的密码进行比较
        if (StringUtils.equals(password, user.getuPass())) {
            return user;
        }
        log.error("密码有误");
        return null;
    }

    @Override
    public Map<String, Object> checkUserName(String username) {
        Map<String,Object> map = new HashMap<>();
        map.put("state",userMapper.checkUserName(username));
        return map;
    }

    @Override
    public Map<String, Object> selectList() {
        List<Map<String, Object>> list = userMapper.selectList();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月");
        for (Map<String, Object> map : list) {
            String time = sdf.format(map.get("createTime"));
            map.put("createTime", time);

        }
        Map<String, Object> map = new HashMap<>();
        map.put("data", list);
        return map;
    }

    @Override
    public int saveMaster(User user) {
        // 创建主管的同时，生成一个公司主键id，创建一条空的公司数据
        String companyId = UUIDUtil.uuid();
        Company company = new Company();
        company.setId(companyId);
        company.setName(user.getcName());
        company.setCreateTime(new Date());
        user.setId(UUIDUtil.uuid());
        user.setuCreateTime(new Date());
        // 加盐加密
        String salt = CodecUtils.generateSalt();
        user.setSalt(salt);
        user.setuPass(CodecUtils.md5Hex(Constant.USER_INITIAL_PASSWORD, salt));
        user.setRoles("admin");   // 主管权限标识符
        user.setCompanyId(companyId);
        companyMapper.saveCompany(company);
        return userMapper.insertUser(user);
    }

    @Override
    public void insertSubUser(HttpServletRequest request, Integer number) throws Exception {
        String token = request.getHeader("token");
        UserInfo userInfo = JwtUtils.getInfoFromToken(token, this.jwtProperties.getKey());
        String companyId = userInfo.getCompanyId();
        // 查找出该公司所有的子用户的名称，并放入set集合中
        LinkedHashSet<String> userSet = userMapper.selectAllSubUser(companyId);
        int len = userSet.size();
        for (int i = 0; i < number; i++) {
            while (userSet.size() < len + number) {
                userSet.add("user" + getRandom(4));
            }
        }
        List<String> list = new ArrayList<>(userSet);
        for (int i = len; i < list.size(); i++) {
            User user = new User();
            user.setuName(list.get(i));
            user.setId(UUIDUtil.uuid());
            user.setCompanyId(companyId);
            user.setuCreateTime(new Date());
            String salt = CodecUtils.generateSalt();
            user.setSalt(salt);
            user.setuPass(CodecUtils.md5Hex(Constant.SUB_USER_INITAL_PASSWORD, salt));
            user.setRoles("user");
            // 创建用户
            userMapper.insertUser(user);
        }

//        for (int i = 0; i < list.size(); i++) {
////            System.out.println(list.get(i));
////        }
    }

    @Override
    public List<User> selectSubUserList(HttpServletRequest request) throws Exception {
        String token = request.getHeader("token");
        UserInfo userInfo = JwtUtils.getInfoFromToken(token, this.jwtProperties.getKey());
        String companyId = userInfo.getCompanyId();
        return userMapper.selectSubUserList(companyId);
    }

    @Override
    public List<User> selectAllMaster() {
        return userMapper.selectAllMaster();
    }

    @Override
    public User getMasterBelong(HttpServletRequest request) throws Exception {
        String token = request.getHeader("token");
        UserInfo userInfo = JwtUtils.getInfoFromToken(token, this.jwtProperties.getKey());
        String companyId = userInfo.getCompanyId();
        return userMapper.getMasterBelong(companyId);
    }

    @Override
    public Company getCompanyBelong(HttpServletRequest request) throws Exception {
        String token = request.getHeader("token");
        UserInfo userInfo = JwtUtils.getInfoFromToken(token, this.jwtProperties.getKey());
        String companyId = userInfo.getCompanyId();
        return companyMapper.getCompanyBelong(companyId);
    }

    @Override
    public int deleteMaster(String id) {
        // 通过删除公司从而删除其他以公司id为外键的表数据，级联删除
        String companyId = userMapper.selectUserById(id).getCompanyId();
        return companyMapper.delete(companyId);
    }

    private void addLoginLog(String ip, User user) {
        SystemLog systemLog = new SystemLog();
        systemLog.setId(UUIDUtil.uuid());
        systemLog.setfUserName(user.getuName());
        systemLog.setfUserId(user.getId());
        // 获取请求ip
//        systemLog.setfUserIp(IpUtils.getIpAddr(request));
        systemLog.setfUserIp(ip);
        systemLog.setfOperationTime(new Date());
        systemLog.setfLogLevel(1);
        systemLog.setfLogDescribe("成功登录后台");
        systemLog.setfOperationType("select");
        systemLog.setfOperationUnit("user");
        systemLog.setfLocation(IpUtils.getCityInfo(ip).replace("|0", ""));
        // 保存日志
        systemLogMapper.addLog(systemLog);
    }

    public static boolean checkObjFieldIsNotNull(Object obj) {   // true 不为空  false 为空
        boolean flag = false;
        try {
            for (Field f : obj.getClass().getDeclaredFields()) {
                f.setAccessible(true);
                if (f.get(obj) == null || f.get(obj) == "") {
                } else {
                    flag = true;
                }
            }
        } catch (Exception e) {
            return false;
        }
        return flag;
    }

    /**
     * 获取随机四位数字组合:
     * 该方法是预设一个数据源，然后通过Random类的nextInt方法获取到一个随机整数，将这个整数作为数据源数组的下标，
     * 再通过循环的方法来组成一个随机数。这里还可以在数据源中补充上字母，就相当于生成带字母的验证码
     *
     * @param len
     * @return
     */
    private static String getRandom(int len) {
        String source = "0123456789";
        Random random = new Random();
        StringBuilder rs = new StringBuilder();
        for (int i = 0; i < len; i++) {
            rs.append(source.charAt(random.nextInt(10)));
        }
        return rs.toString();
    }
}
